package com.ttbj.product.servicelog;

import java.lang.reflect.Method;
import java.util.Date;


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.ttbj.api.dto.log.SystemLogDto;
import com.ttbj.constant.annotation.SystemServiceLog;
import com.ttbj.systemlog.dao.SystemLogMapper;

@Aspect
public class ServiceLogRecord {

	@Autowired
	private SystemLogMapper systemLogMapper;

	private static Logger LOGGER = LoggerFactory.getLogger(ServiceLogRecord.class);

	// Service层切点
	@Pointcut("@annotation(com.ttbj.constant.annotation.SystemServiceLog)")
	public void serviceAspect() {

	}
	
	/**  
     * 异常通知 用于拦截service层记录异常日志  
     * @param joinPoint 切点
     * @param e  异常
     */    
     @AfterThrowing(pointcut = "serviceAspect()", throwing = "e")    
     public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
    	try {
			SystemLogDto systemLogDto = new SystemLogDto();
			systemLogDto.setDescription(getServiceMethodDescription(joinPoint));
			systemLogDto.setType(1);	//日志类型，出现异常
			systemLogDto.setParams(optionContent(joinPoint.getArgs(), joinPoint.getSignature().getName()));
			systemLogDto.setCreateDate(new Date());
			systemLogDto.setExceptionCode(e.getClass().getName());
			systemLogDto.setExceptionDetail(e.getMessage());
			systemLogDto.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));
			this.systemLogMapper.insertSystemLog(systemLogDto);
		} catch (Exception e1) {
			e1.printStackTrace();
			LOGGER.info("异常增强，异常信息", e1);
		}
     }    
	
	
	/**
	 * 获取注解中对方法的描述 用于service层
	 * @param joinPoint
	 * @return 描述信息
	 * @throws Exception
	 */
	public static String getServiceMethodDescription(JoinPoint joinPoint) throws Exception{
		//获取目标对象的方法名，包名+类名
		String targetName = joinPoint.getTarget().getClass().getName();
		//获取连接点处的方法信息，inser()这种形式
		String methodName = joinPoint.getSignature().getName();
		//获取连接点处方法的参数
		Object[] arguments = joinPoint.getArgs();
		//通过反射来获取一个类对象
		Class targetClass = Class.forName(targetName);
		//
		Method[] methods = targetClass.getMethods();
		//方法描述
		String description = "";
		
		for (Method method : methods) {
			if (method.getName().equals(methodName)) {
				Class[] clazzs = method.getParameterTypes();
				if (clazzs.length == arguments.length) {
					description = method.getAnnotation(SystemServiceLog.class).description();
					break;
				}
			}
		}
		return description;
	}
	
	/**
	 * 使用Java反射来获取被拦截方法(insert、update)的参数值， 将参数值拼接为操作内容
	 * @param args
	 * @param mName
	 * @return
	 */
	public String optionContent(Object[] args, String mName) {
		if (args == null) {
			return null;
		}
		StringBuffer rs = new StringBuffer();
		rs.append(mName);
		String className = null;
		int index = 1;
		// 遍历参数对象
		for (Object info : args) {
			// 获取对象类型
			className = info.getClass().getName();
			className = className.substring(className.lastIndexOf(".") + 1);
			rs.append("[参数" + index + "，类型:" + className + "，值:");
			// 获取对象的所有方法
			Method[] methods = info.getClass().getDeclaredMethods();
			// 遍历方法，判断get方法
			for (Method method : methods) {
				String methodName = method.getName();
				// 判断是不是get方法
				if (methodName.indexOf("get") == -1) {// 不是get方法
					continue;// 不处理
				}
				Object rsValue = null;
				try {
					// 调用get方法，获取返回值
					rsValue = method.invoke(info);
				} catch (Exception e) {
					continue;
				}
				// 将值加入内容中
				rs.append("(" + methodName + ":" + rsValue + ")");
			}
			rs.append("]");
			index++;
		}
		return rs.toString();
	}
}
